# coding=gbk
"""
Created on 2016/7/6 0006

@author: Experiment

@about: SVM on abalone
"""
import os

import numpy as np
from sklearn import svm

PATH_ORG = os.getcwd() + os.sep + "data" + os.sep + "abalone" + os.sep

DIC_VALUE_SEX = {"M": 0, "F": 1, "I": 2}
KERNELS = ["linear", "poly", "rbf", "sigmoid"]


class Expmt02():
    def __init__(self):
        pass

    def __getData(self, ratio=0.75):
        data = np.loadtxt(PATH_ORG + "abalone.data", delimiter=",",
                          dtype=str)
        data_bin = self.__toBin(data)
        data_nor = self.__toNor(data_bin)
        return self.__toSplit(data_nor, ratio)

    def __toBin(self, data):
        data_bin = np.zeros((data.shape[0], data.shape[1] + 1))
        for i in range(data.shape[0]):
            for j in range(data.shape[1]):
                if j == 0:
                    data_bin[i, 0] = DIC_VALUE_SEX[data[i, 0]] / 2
                    data_bin[i, 1] = DIC_VALUE_SEX[data[i, 0]] % 2
                else:
                    data_bin[i, j + 1] = float(data[i, j])
        return data_bin

    def __toNor(self, data):
        data_min = np.min(data, axis=0)
        data_max = np.max(data, axis=0)
        data_diff = data_max - data_min
        for i in range(2, data.shape[1] - 1):
            data[:, i] = (data[:, i] - data_min[i]) / data_diff[i]
        return data

    def __toSplit(self, data, ratio):
        np.random.shuffle(data)
        length = int(ratio * data.shape[0])
        return data[:length, :], data[length:, :]

    def process1(self):
        train_set, test_set = self.__getData()
        x_train, y_train = train_set[:, :-1], train_set[:, -1].ravel()
        x_test, y_test = test_set[:, :-1], test_set[:, -1].ravel()
        for kernel in KERNELS:
            clf = svm.SVR(kernel=kernel)
            clf.fit(x_train, y_train)
            print kernel, ":\t", self.__score(clf, x_test, y_test)

    def __score(self, model, x, y):
        return np.mean(np.abs(model.predict(x) - y) / y)

    def process2(self):
        import matplotlib.pyplot as plt
        train_set, test_set = self.__getData()
        x_train, y_train = train_set[:, :-1], train_set[:, -1].ravel()
        x_test, y_test = test_set[:, :-1], test_set[:, -1].ravel()
        scores = np.zeros(5)
        for degree in range(1, scores.shape[0] + 1):
            clf = svm.SVR(kernel="linear", degree=degree)
            clf.fit(x_train, y_train)
            scores[degree - 1] = self.__score(clf, x_test, y_test)
        plt.title("Linear SVM on different degrees")
        plt.plot(np.arange(1, scores.shape[0] + 1, 1), scores)
        plt.show()


if __name__ == '__main__':
    print "**************start**************\n\n"

    # Expmt02().process1()
    Expmt02().process2()

    print "\n\n**************end**************"
